package cn.com.zhaoweiping.ie;

import cn.com.zhaoweiping.ie.RowReadStatus.Status;
import com.google.common.collect.Lists;
import java.io.File;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * 读数据上下文默认实现<br>
 *
 * @author 冰羽
 * @version 2.2.0
 */
@Slf4j
public class SimpleReadContext implements ReadContext<RowReadStatus> {

  /** 30分钟 */
  private static final long _30_MINUTES_ = 1800L;

  @Getter @Setter private File file;

  @Setter private Status status = Status.NOT_STARTED;

  @Setter private Status excelStatus = Status.NOT_STARTED;

  private volatile int readIndex = 0;
  private long createTime;
  /** Excel中Sheet个数 */
  @Getter private int sheetCounts;

  /** 对于当前Sheet所有的行的读取状态记录 */
  @Getter private List<RowReadStatus> readStatuses = new CopyOnWriteArrayList<>();

  public SimpleReadContext(int sheetCounts) {
    this.sheetCounts = sheetCounts;
    this.createTime = System.currentTimeMillis();
  }

  public String getFileName() {
    try {
      return getFile().getName();
    } catch (Exception e) {
      if (e instanceof NullPointerException) {
        return "未获取到文件, NullPointerException";
      } else {
        return e.getMessage();
      }
    }
  }

  public int getTotal() {
    return this.readStatuses.size();
  }

  public long getFailTotal() {
    return this.readStatuses.stream().filter(s -> s.isStatus() == false).count();
  }

  public List<RowReadStatus> getPartFails(int limit) {
    return this.readStatuses.stream()
        .filter(s -> s.isStatus() == false)
        .limit(limit)
        .collect(Collectors.toList());
  }

  public void setStatusBlank(Integer rowIndex, String message) {
    RowReadStatus rowReadStatus = new RowReadStatus();
    rowReadStatus.setRowIndex(rowIndex);
    rowReadStatus.setStatus(false);
    rowReadStatus.setBlank(true);
    rowReadStatus.setMessage(message);

    this.readStatuses.add(rowReadStatus);
  }

  public void setStatus(Integer rowIndex, boolean status, String message) {
    RowReadStatus rowReadStatus = new RowReadStatus();
    rowReadStatus.setRowIndex(rowIndex);
    rowReadStatus.setStatus(status);
    rowReadStatus.setBlank(false);
    rowReadStatus.setMessage(message);

    this.readStatuses.add(rowReadStatus);
  }

  @Override
  public boolean removable() {

    // 读取完成或者超时将自动移除
    return (this.status == Status.FINISH && this.readIndex == this.readStatuses.size())
        || (((System.currentTimeMillis() - this.createTime) / (60 * 1000)) > _30_MINUTES_);
  }

  @Override
  public Status readStatus() {
    return status;
  }

  @Override
  public Status readExcelStatus() {
    return excelStatus;
  }

  @Override
  public List<RowReadStatus> read() {
    List<RowReadStatus> statuses = Lists.newArrayList();
    if (this.readIndex <= this.readStatuses.size()) {
      for (int i = this.readIndex; i < this.readStatuses.size(); i++) {
        statuses.add(this.readStatuses.get(i));
      }

      this.readIndex = this.readStatuses.size();

      if (this.readIndex < this.readStatuses.size() && this.status == Status.FINISH) {
        for (int i = this.readIndex; i < this.readStatuses.size(); i++) {
          statuses.add(this.readStatuses.get(i));
        }
      }
    }

    return statuses;
  }
}
